import React, { useState, useEffect, useRef } from "react";
import type { QuickFilterItem, QuickFilterItemOptions } from "../type";
import { isUndefined, isPromise } from "@ct0/functions";
import Input from "./Input";
import Overlay from "./Overlay";
import Cascader from "../../Cascader";
import Select from "./Select";
import Dropdown from "./Dropdown";
import DatatimeRange, { formatNumberTimestamp } from "./DatetimeRange";
import Datetime from "./Datetime";
import TagChoice from "./TagChoice";
import type { CascaderOptions } from "../../Cascader/type";
import TimeRangePickerFilter, { getLabel } from "./TimeRangePickerFilter";

export default function Item({
  value,
  field,
  shadow,
  onChange,
  emptyLabel,
  getPopupContainer,
}: {
  value: any;
  shadow?: boolean;
  field: QuickFilterItem;
  onChange: (key: string, value: any) => void;
  emptyLabel?: string;
  getPopupContainer?: (node: HTMLElement) => HTMLElement;
}) {
  const { key, validate, placeholder } = field;
  const [visible, setVisible] = useState(false);
  const [errmsg, setErrmsg] = useState<string>();
  const functionOptionRef = useRef(false);
  const [options, setOptions] = useState<QuickFilterItemOptions>([]);
  const [cascaderOptions, setCascaderOptions] =
    useState<QuickFilterItemOptions>();

  const propsOptions = field.type != "custom" ? field.options : undefined;

  let style: React.CSSProperties = {};

  const optionsIsFunction = typeof propsOptions == "function";
  useEffect(() => {
    /**
     * 为了避免方法类型的参数，每次重新渲染时重新执行，这里只执行一次方法类型的 options
     * 如果想要动态更新 options，可以传值类型 options，而不是用方法
     */
    if (optionsIsFunction) {
      if (!functionOptionRef.current) {
        updateOpts(undefined, value);
        functionOptionRef.current = true;
      }
    } else {
      updateOpts(undefined, value);
    }
  }, [propsOptions]);

  useEffect(() => {
    if (!visible) updateOpts(undefined, value);
  }, [visible]);

  const updateOpts = (text?: string, value?: Array<string | number>) => {
    if (isUndefined(propsOptions)) return;
    else if (optionsIsFunction) {
      const opt = propsOptions(text, value);
      if (isPromise(opt)) opt.then((r) => setOptions(r));
      // 是方法，但不是 Promise 方法的时候，直接设置
      else setOptions(opt as any);
    } else {
      if (text) {
        const opts = propsOptions.filter(
          (i) =>
            i.label.includes(text) ||
            String(i.value).includes(text) ||
            value?.includes(i.value)
        );
        setOptions(opts);
      } else {
        setOptions(propsOptions);
      }
    }
  };

  const handler = (value?: any, visible?: boolean) => {
    const check = validate?.(value);
    if (check?.isValid === false) {
      setErrmsg(check.errmsg);
      return;
    } else {
      setErrmsg(undefined);
    }

    onChange(key, value);

    if (visible === true) {
    } else setVisible(false);
  };

  let overlay: JSX.Element | undefined = undefined;
  let valueLabel: string | undefined = "";
  let valueCount = 0;

  if (field.type == "string") {
    overlay = (
      <Input
        type="string"
        value={value}
        placeholder={placeholder ?? "请输入" + field.label}
        onChange={handler}
      />
    );
    valueLabel = value;
  } else if (field.type == "number") {
    overlay = (
      <Input
        type="number"
        value={value}
        placeholder={placeholder ?? "请输入" + field.label}
        onChange={handler}
      />
    );
    valueLabel = value;
  } else if (field.type == "cascader") {
    const loadData = async (selectedOptions: CascaderOptions) => {
      if (field.meta?.cascaderLoadData) {
        const opts = await field.meta.cascaderLoadData(selectedOptions);
        setCascaderOptions(opts);
      }
    };
    overlay = (
      <div style={{ padding: "10px" }}>
        <Cascader
          placeholder={placeholder ?? "请选择" + field.label}
          value={value}
          options={cascaderOptions ?? options}
          onChange={handler}
          loadData={loadData}
          changeOnSelect={field.meta?.cascaderChangeOnSelect}
          allowClear={false}
          placement={field.meta?.placement}
        />
      </div>
    );
    const labels: Array<string | number> = [];
    const getLabel = (
      options: QuickFilterItemOptions,
      value?: Array<string | number>
    ) => {
      if (isUndefined(value)) return;
      if (value.length == 0) return;
      for (const i of options) {
        if (i.value == value[0]) {
          labels.push(i.label);
          getLabel(i.children || [], value.slice(1));
          break;
        }
      }
    };
    getLabel(options, value);
    valueLabel = labels.join(" / ");
  } else if (field.type == "select") {
    overlay = (
      <Select
        onInputChange={(text) => updateOpts(text, value)}
        options={options}
        placeholder={placeholder ?? "请搜索" + field.label}
        search={field?.meta?.selectWithSearch ?? optionsIsFunction}
        value={value}
        onValueChange={handler}
      />
    );
    valueLabel = isUndefined(value) ? "" : String(value);
    for (const i of options) if (i.value == value) valueLabel = i.label;
  } else if (field.type == "multi_select") {
    overlay = (
      <Select
        multiValue={value ?? []}
        onInputChange={(text) => updateOpts(text, value)}
        multiple
        placeholder={placeholder ?? "请搜索" + field.label}
        search={field?.meta?.selectWithSearch ?? optionsIsFunction}
        options={options}
        onMultiValueChange={(v) => handler(v, true)}
      />
    );
    const labels: Array<string> = [];
    value?.forEach((v: string | number) => {
      let findFlag = false;
      for (const i of options) {
        if (i.value == v) labels.push(i.label);
        findFlag = true;
      }
      if (!findFlag) labels.push(String(v));
    });
    valueLabel = labels.join("、");
    valueCount = value?.length;
  } else if (field.type == "time_range") {
    overlay = (
      <DatatimeRange value={value} onChange={handler} meta={field.meta} />
    );
    style = { maxWidth: "none" };
    const { isChinese = true } = field.meta || {};
    valueLabel = value
      ? `${formatNumberTimestamp(value[0])} ${
          isChinese ? "到" : "-"
        } ${formatNumberTimestamp(value[1])}`
      : "";
  } else if (field.type == "datetime") {
    overlay = <Datetime value={value} onChange={handler} meta={field.meta} />;
    valueLabel = value ? formatNumberTimestamp(value) : "";
  } else if (field.type === "tag_choice") {
    overlay = (
      <TagChoice value={value} onChange={handler} placeholder={placeholder} />
    );
    valueLabel = (value ?? []).join("、");
    valueCount = value?.length;
  } else if (field.type == "custom") {
    const C = field.component;
    overlay = (
      <C
        placeholder={placeholder}
        value={value}
        onChange={handler}
        options={field.options}
      />
    );
    const labels = field.valueLabel ? field.valueLabel(value) : String(value);
    if (Array.isArray(labels)) {
      valueLabel = labels.join("、");
      valueCount = labels.length;
    } else {
      valueLabel = labels;
    }
  } else if (field.type == "multi_type_time") {
    overlay = (
      <TimeRangePickerFilter value={value} onChange={handler} {...field.meta} />
    );
    style = { maxWidth: "none" };
    valueLabel = getLabel({ value });
  }

  if (isUndefined(overlay)) {
    overlay = (
      <div style={{ padding: "10px" }}>无法渲染 {JSON.stringify(field)}</div>
    );
  }

  let icon: string | undefined;
  if (field.type == "time_range" || field.type == "datetime") icon = "calendar";

  return (
    <Dropdown
      visible={visible}
      shadow={shadow}
      style={style}
      icon={icon}
      onVisibleChange={setVisible}
      overlay={<Overlay errmsg={errmsg}>{overlay}</Overlay>}
      label={field.label}
      valueLabel={valueLabel}
      valueCount={valueCount}
      onClear={handler}
      emptyLabel={emptyLabel}
      getPopupContainer={getPopupContainer}
    />
  );
}
